package model

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/go-xorm/xorm"

	"gitee.com/goframe/lt-collector/libs/libce"
	"gitee.com/goframe/lt-collector/libs/orma"
)

const (
	_     = iota
	TSsc  //时时彩
	TPk10 //赛车类
	TFt   //飞艇类
	TKl8  //快乐8
	TPCdd //PC蛋蛋
	T11x5 //11选5
	TKLsf //快乐10分
	TK3   //快三
	THk6  //六合彩
)

const (
	_     = iota
	SCKcw //开采网
	SC168 //168
	SCBy  //必赢
)

const (
	SCSys = -100
	SCTx  = -99
)

var (
	Types = map[int]string{
		TSsc:  "时时彩",
		TPk10: "赛车",
		TFt:   "飞艇",
		TKl8:  "快乐8",
		TPCdd: "PC蛋蛋",
		T11x5: "11选5",
		TKLsf: "快乐10分",
		TK3:   "快三",
		THk6:  "六合彩",
	}

	Sources = map[int]string{
		SCTx:  "腾讯分分彩",
		SCSys: "系统彩",
		SCKcw: "开采网",
		SC168: "168kai",
		SCBy:  "必赢",
	}
)

type (
	SysSetting struct {
		orma.BaseModel `xorm:"extends"`

		Key   string `json:"key" xorm:"varchar(50) notnull unique"`
		Value string `json:"value" xorm:"json"`
	}
	//GameTypes 彩种类型
	GameTypes struct {
		orma.BaseModel `xorm:"extends"`

		TypeID int    `json:"type_id" xorm:"notnull unique comment(彩种类型ID)"`
		Name   string `json:"name"`
	}
	//GameLotteries 彩种列表
	GameLotteries struct {
		orma.BaseModel `xorm:"extends"`

		TypeID int    `json:"type_id" xorm:"notnull index comment(彩种类型ID)"`
		Name   string `json:"name" xorm:"varchar(20) notnull unique comment(彩种名称英文)"`
		NameCN string `json:"name_cn" xorm:"varchar(50) notnull comment(彩种名称中文)"`
		Enable bool   `json:"enable" xorm:"notnull index comment(是否有效)"`
		IsSys  bool   `json:"is_sys" xorm:"notnull index comment(是否是一个系统彩)"`

		CollectSourceIds []int `json:"collect_source_ids" xorm:"notnull comment(资源采集站点列表)"`
	}

	//GameCollectSource 采集资源站点
	GameCollectSource struct {
		orma.BaseModel `xorm:"extends"`

		Name       string `json:"name" xorm:"varchar(50) notnull comment(站点名称)"`
		SourceURL  string `json:"source_url" xorm:"varchar(200) notnull comment(站点地址)"`
		SourceType int    `json:"source_type" xorm:"notnull index comment(站点类型)"`
	}

	//GameSourceTypes 采集资源类型
	GameSourceTypes struct {
		orma.BaseModel `xorm:"extends"`

		Name string `json:"name" xorm:"varchar(50) notnull comment(类型名称)"`
		Type int    `json:"type" xorm:"notnull index comment(站点类型)"`
	}

	//采集资源类型采集参数-开采网
	GameSourceParamKcw struct {
		orma.BaseModel `xorm:"extends"`

		Gid    int64  `json:"gid" xorm:"notnull comment(彩种ID)"`
		Code   string `json:"code" xorm:"varchar(20) notnull comment(开采网code)"`
		Format string `json:"format" xorm:"varchar(20) notnull comment(序列化类型_默认json)"`
	}
	//采集资源类型采集参数-168kai
	GameSourceParam168 struct {
		orma.BaseModel `xorm:"extends"`

		Gid     int64  `json:"gid" xorm:"notnull comment(彩种ID)"`
		LotCode string `json:"lot_code" xorm:"varchar(20) notnull comment(168lotCode)"`
	}

	//开奖时间段
	OpenTimePlan struct {
		//开始时间;精确到秒:00:00:00
		Start string `json:"start"`
		//结束时间;精确到秒:00:00:00
		Stop string `json:"stop"`
		//周期,秒数
		PeriodSeconds int64 `json:"period_seconds"`
	}
	//开奖时间计划
	GameIssuePlan struct {
		orma.BaseModel `xorm:"extends"`

		Gid int64 `json:"gid" xorm:"notnull index comment(彩种ID)"`
		//时间段
		TimePlans []OpenTimePlan `json:"time_plans" xorm:"json notnull comment(开奖时间段)"`
		//期号+1的彩种
		IssueAddOne bool `json:"issue_add_one" xorm:"notnull comment(是否是期号+1的彩种)"`
		//第一期时间;精确到秒:00:00:00
		FirstIssueTime string `json:"first_issue_time" xorm:"varchar(10) notnull comment(每日第一期开奖时间)"`
		//最后一期时间;精确到秒:00:00:00
		LastIssueTime string `json:"last_issue_time" xorm:"varchar(10) notnull comment(每日最后一期开奖时间)"`
	}
	//OpenData 开奖数据
	OpenData struct {
		orma.BaseModel `xorm:"extends"`

		OtherData interface{} `json:"other_data,omitempty" xorm:"-"`

		LotName   string `json:"lot_name" xorm:"-"`
		LotNameCN string `json:"lot_name_cn" xorm:"-"`

		Gid int64 `json:"gid" xorm:"notnull index comment(彩种ID)"`
		//开奖期号
		Issue string `json:"issue" xorm:"varchar(20) notnull index comment(开奖期号)"`
		//开奖号码
		OpenCode string `json:"open_code" xorm:"varchar(200) notnull comment(开奖号码)"`
		//开奖时间
		OpenTime *orma.JSONTime `json:"open_time" xorm:"notnull comment(开奖时间)"`
		//开奖时间戳
		OpenTimestamp int64 `json:"open_timestamp" xorm:"notnull comment(开奖时间戳)"`
		//下期开奖期号
		NextIssue string `json:"next_issue" xorm:"varchar(20) notnull comment(下期开奖期号)"`

		NextOpenTime *orma.JSONTime `json:"next_open_time" xorm:"notnull comment(下期开奖时间)"`

		NextOpenTimestamp int64 `json:"next_open_timestamp" xorm:"notnull comment(下期开奖时间戳)"`

		FromSourceID int `json:"from_source_id" xorm:"notnull comment(采集源类型ID)"`
	}
	//GameIssueCheck 彩种期号校对数据
	GameIssueCheck struct {
		orma.BaseModel `xorm:"extends"`

		Gid      int64          `json:"gid,omitempty" xorm:"notnull index comment(彩种ID)"`
		Issue    string         `json:"issue,omitempty" xorm:"varchar(20) notnull comment(开奖期号)"`
		OpenTime *orma.JSONTime `json:"open_time,omitempty" xorm:"notnull comment(开奖时间)"`
	}
)

func (m *OpenData) BeforeSet(name string, cell xorm.Cell) {
	m.BaseModel.BeforeSet(name, cell)
	if name == "open_time" || name == "OpenTime" {
		m.OpenTime = &orma.JSONTime{}
	}
	if name == "next_open_time" || name == "NextOpenTime" {
		m.NextOpenTime = &orma.JSONTime{}
	}
}

func (m *GameIssueCheck) BeforeSet(name string, cell xorm.Cell) {
	m.BaseModel.BeforeSet(name, cell)
	if name == "open_time" || name == "OpenTime" {
		m.OpenTime = &orma.JSONTime{}
	}
}

func (m *OpenData) AutoClear() {
	m.autoClear()
	_ = ModeTask.AddFunc("0 0 1 * * *", m.autoClear)
}

func (m *OpenData) autoClear() {
	sqlExecuteText := `DELETE FROM {table} WHERE created < date_sub(now(), INTERVAL 2 DAY);
ALTER TABLE {table} ENGINE 'INNODB';`
	sqlExecuteText = strings.Replace(sqlExecuteText, "{table}", "open_data", -1)
	buf := bytes.NewBufferString(sqlExecuteText)
	_, _ = orma.GetEngine().Import(buf)
}

func (m *GameIssuePlan) AfterDelete() {
	libce.DeleteCacheByKey(m, fmt.Sprintf("gid:%d", m.Gid))
}

func (m *GameIssuePlan) AfterUpdate() {
	libce.DeleteCacheByKey(m, fmt.Sprintf("gid:%d", m.Gid))
}

func (m *GameIssuePlan) getByGid(gid int64) error {
	return libce.CacheBindModelByKey(m, fmt.Sprintf("gid:%d", gid), func() error {
		return orma.NormalGet(m.Session().Where("gid=?", gid).Get(m))
	})
}

func (m *GameSourceParam168) AfterDelete() {
	libce.DeleteCacheByKey(m, fmt.Sprintf("gid:%d", m.Gid))
}

func (m *GameSourceParam168) AfterUpdate() {
	libce.DeleteCacheByKey(m, fmt.Sprintf("gid:%d", m.Gid))
}

func (m *GameSourceParamKcw) AfterDelete() {
	libce.DeleteCacheByKey(m, fmt.Sprintf("gid:%d", m.Gid))
}

func (m *GameSourceParamKcw) AfterUpdate() {
	libce.DeleteCacheByKey(m, fmt.Sprintf("gid:%d", m.Gid))
}

func (m *GameCollectSource) BeforeInsert() {
	m.trimSpace()
}

func (m *GameCollectSource) BeforeUpdate() {
	m.trimSpace()
}

func (m *GameCollectSource) AfterDelete() {
	deleteCacheID(m)
}

func (m *GameCollectSource) AfterUpdate() {
	_ = ResetCacheID(m)
}

func (m *GameSourceTypes) InitData() interface{} {
	data := make([]*GameSourceTypes, 0)
	for typeID, name := range Sources {
		data = append(data, &GameSourceTypes{
			Name: name,
			Type: typeID,
		})
	}
	return data
}

func (m *SysSetting) InitData() interface{} {
	return []*SysSetting{{
		Key:   "KCW_Token",
		Value: "",
	}}
}

func (m *GameLotteries) AfterDelete() {
	deleteCacheID(m)
}

func (m *GameLotteries) AfterUpdate() {
	_ = ResetCacheID(m)
}

func (m *SysSetting) AfterDelete() {
	libce.DeleteCacheByKey(m, m.Key)
}

func (m *SysSetting) AfterUpdate() {
	libce.DeleteCacheByKey(m, m.Key)
}

//GetByKey cache value
func (m *SysSetting) GetByKey(key string) error {
	return libce.CacheBindModelByKey(m, key, func() error {
		return orma.NormalGet(m.Session().Where("`key`=?", key).NoCache().NoAutoCondition().Get(m))
	})
}

//InitData 彩种类型初始化数据
func (m *GameTypes) InitData() interface{} {
	data := make([]*GameTypes, 0, len(Types))
	for key, value := range Types {
		data = append(data, &GameTypes{TypeID: key, Name: value})
	}
	return data
}
